using Mono.Cecil;
using Mono.Cecil.Cil;
using Mono.Cecil.Rocks;

namespace Cil.Ast;

public sealed class NewArrayExpression : SingleInstructionExpression
{
	public const int LengthPos = 0;
	public const int MaxNodes = 1;

	public NewArrayExpression(Context context, Instruction position, TypeReference itemType, Expression exp_length) 
		: base(context, position)
	{
		if(exp_length.WritesStack != 1)
		{
			throw new InvalidOperationException(string.Format("Wrong stack items count in exp_length argument: {0}", exp_length.WritesStack));
		}

		// check is length type is int16
		if(exp_length.ReturnType.MetadataType != MetadataType.Int32)
		{
			throw new ArgumentException(string.Format("exp_length should be System.Int32 ({0})", exp_length.ReturnType));
		}

		// base class
		ReturnType = itemType.MakeArrayType();
		ReadsStack = 1;
		WritesStack = 1;
		Nodes = new FixedList<Expression>(MaxNodes);

		// this
		ItemType = itemType;
		LengthExpression = exp_length;
	}

	public TypeReference ItemType { get; private set; }

	public Expression LengthExpression { get { return Nodes[LengthPos]; } set { Nodes[LengthPos] = value; value.ParentNode = this; } }

	public override string ToString()
	{
		return string.Format("new {0}[{1}]", ItemType, LengthExpression);
	}
}

public static partial class IlAst
{
	public static NewArrayExpression CreateArray(Context context, Instruction position, TypeReference itemType, Expression exp_length)
	{
		return new NewArrayExpression(context, position, itemType, exp_length);
	}
}